#include "User_Uart.h"
#include "MQ.h"


/**********************************************
              文件使用说明
1、请将头文件放到main.c里面
2、在main函数初始化中调用User_Uart_Init()
3、在stm32xxxx_it.c中调用Uart_Call_Back()函数
4、在头文件中修改需要的串口，添加或注释
5、如果使用消息队列，在main函数初始化中调用MQ_Init()
     
**********************************************/


Uart_Typedef Uart1_Data,Uart2_Data,Uart3_Data,Uart4_Data;
uint8_t recv_buf = 0;
uint16_t Delay_Time=1000;



/**********************************************
函数名称：User_Uart_Init()
函数作用：HAL库串口初始化函数
使用		：在main函数硬件初始化后调用
调用说明：
外部声明：             
**********************************************/
void User_Uart_Init()
{
  Uart_DMA_Init();
  Uart_IT_Init();  
}


/**********************************************
函数名称：Uart_IT_Init()
函数作用：初始化串口中断
使用		：
          使用时要注意修改中断参数
调用说明：函数被User_Uart_Init调用
外部声明：             
**********************************************/
void Uart_IT_Init(void)
{
	#ifdef uart1_IT
		Uart1_Data.huart=&huart1;
		HAL_UART_Receive_IT(&huart1, (uint8_t*)&recv_buf, 1);
  #endif
  #ifdef uart2_IT
    Uart2_Data.huart=&huart2;
    HAL_UART_Receive_IT(&huart2, (uint8_t*)&recv_buf, 1);
  #endif
}

/**********************************************
函数名称：Shell_Intercep()
函数作用：Shell截获串口数据
使用		：在串口接收到数据后回馈命令台
调用说明：只有在使用shell调用
外部声明：             
**********************************************/
void Shell_Intercep(void)
{
  #ifdef Use_Shell
  const uint8_t cm_arry1[]="AT+Shell_Flag1";
  const uint8_t cm_arry0[]="AT+Shell_Flag0";
  uint8_t Result;
  if(Shell_Uart_Data.Uart_Receive_Cunt==1)  //只有接收到一个数据才会执行
  {
    if(Shell_Flag)
    {
      shellHandler(&shell, Shell_Uart_Data.Uart_Receive_Arry[0]);
      Uart_DMA_Data_Rest(&Shell_Uart_Data);
    }    
  }
  else if(Shell_Uart_Data.Uart_Receive_Cunt==14)
  {   
    if(Shell_Uart_Data.Uart_Receive_Arry[13]==0x31)  //开启
    {
      Result=strcmp((char *)Shell_Uart_Data.Uart_Receive_Arry,(char *)cm_arry1);
      if(Result==0)
      {
        Shell_Flag=1;
        Uart_DMA_Data_Rest(&Shell_Uart_Data);
        printf("Shell Start");
      } 
    }
    else if(Shell_Uart_Data.Uart_Receive_Arry[13]==0x30) //关闭的指令
    {
      Result=strcmp((char *)Shell_Uart_Data.Uart_Receive_Arry,(char *)cm_arry0);
      if(Result==0)
      {
        Shell_Flag=0;
        Uart_DMA_Data_Rest(&Shell_Uart_Data);
        printf("Shell Close");
      } 
    }
  }
  #endif 
}

/**********************************************
函数名称：Uart_DMA_Init()
函数作用：串口DMA初始化函数
使用		：函数被User_Uart_Init调用
调用说明：
外部声明：             
**********************************************/
void Uart_DMA_Init()
{
  #ifdef uart1_DMA
  Uart1_Data.huart=&huart1;
  __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);         //串口空闲中断  
  HAL_UART_Receive_DMA(&huart1,Uart1_Data.Uart_Receive_Arry,Data_Len_Max);				//Lora的DMA初始化  
  #endif

  #ifdef uart2_DMA
  Uart2_Data.huart=&huart2;
  __HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE);         //串口空闲中断

  HAL_UART_Receive_DMA(&huart2,Uart2_Data.Uart_Receive_Arry,Data_Len_Max);				//Lora的DMA初始化
  
  #endif
  
  #ifdef uart3_DMA
  Uart3_Data.huart=&huart3;
  __HAL_UART_ENABLE_IT(&huart3,UART_IT_IDLE);         //串口空闲中断

  HAL_UART_Receive_DMA(&huart3,Uart3_Data.Uart_Receive_Arry,Data_Len_Max);				//Lora的DMA初始化
  
  #endif  
  
  #ifdef uart4_DMA 
  Uart4_Data.huart=&huart4;
  __HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE);         //串口空闲中断

  HAL_UART_Receive_DMA(&huart2,Uart2_Data.Uart_Receive_Arry,Data_Len_Max);				//Lora的DMA初始化
  
  #endif
}

/**********************************************
函数名称：Uart_DMA_Data_Rest()
函数作用：串口DMA清除数据
使用		：在处理完串口DMA的数据后，调用可以一键清除所有数据
调用说明：注意，此函数会清空所有数据，包括接收长度，一定要在最后
          调用此函数
外部声明：             
**********************************************/
void Uart_DMA_Data_Rest(Uart_Typedef *uart)
{
  uart->Uart_Receive_Complete=0; 
  uart->Uart_Receive_Cunt=0;
  memset(uart->Uart_Receive_Arry,0,sizeof(uart->Uart_Receive_Arry));
  HAL_UART_Receive_DMA(uart->huart,uart->Uart_Receive_Arry,Data_Len_Max);				//Lora的DMA初始化
}


/**********************************************
函数名称：Uart_Call_Back()
函数作用：DMA数据处理函数
使用		：函数在stm32xx_it.c 文件中的USARTX_IRQHandler中调用
调用说明：
外部声明：             
**********************************************/
void Uart_Call_Back() //由中断发起调用，处理DMA中断消息
{
 
  #ifdef  uart1_DMA
  extern DMA_HandleTypeDef hdma_usart1_rx;
  if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE))	//如果置1了，代表已经接收完毕了
	{
		__HAL_UART_CLEAR_IDLEFLAG(&huart1);
		HAL_UART_DMAStop(&huart1);
		//Uart1_Data.Uart_Receive_Cunt=Data_Len_Max-hdma_usart1_rx.Instance->NDTR;
    Uart1_Data.Uart_Receive_Cunt=Data_Len_Max-hdma_usart1_rx.Instance->CNDTR;
    DMA1_Channel2->CNDTR=Data_Len_Max;
		Uart1_Data.Uart_Receive_Complete = 1;		//完成了接收，在前台任务要将DMA再次打开
    Mes_uart_Press(0xa1,Uart1_Data.Uart_Receive_Arry,Uart1_Data.Uart_Receive_Cunt);
    Uart_DMA_Data_Rest(&Uart1_Data);
	}
  #endif
  
  
  #ifdef uart2_DMA 
  extern DMA_HandleTypeDef hdma_usart2_rx;
  if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE))	//如果置1了，代表已经接收完毕了
	{
		__HAL_UART_CLEAR_IDLEFLAG(&huart2);
		HAL_UART_DMAStop(&huart2);
    //Uart2_Data.Uart_Receive_Cunt=Data_Len_Max-hdma_usart2_rx.Instance->NDTR;
		Uart2_Data.Uart_Receive_Cunt=Data_Len_Max-hdma_usart2_rx.Instance->CNDTR;
		DMA1_Channel2->CNDTR=Data_Len_Max;
		Uart2_Data.Uart_Receive_Complete = 1;		//完成了接收，在前台任务要将DMA再次打开
    Mes_uart_Press(0xa2,Uart2_Data.Uart_Receive_Arry,Uart2_Data.Uart_Receive_Cunt);
    Uart_DMA_Data_Rest(&Uart2_Data);
	}
  #endif
  
  #ifdef uart3_DMA 
  extern DMA_HandleTypeDef hdma_usart3_rx;
  if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE))	//如果置1了，代表已经接收完毕了
	{
		__HAL_UART_CLEAR_IDLEFLAG(&huart3);
//		huart3.Instance->ISR;
//		huart3.Instance->RDR;
		HAL_UART_DMAStop(&huart3);
		Uart3_Data.Uart_Receive_Cunt=Data_Len_Max-hdma_usart3_rx.Instance->CNDTR;
		DMA1_Channel1->CNDTR=Data_Len_Max;
		Uart3_Data.Uart_Receive_Complete = 1;		//完成了接收，在前台任务要将DMA再次打开
    Mes_uart_Press(0xa1,Uart3_Data.Uart_Receive_Arry,Uart3_Data.Uart_Receive_Cunt);
    Uart_DMA_Data_Rest(&Uart3_Data);
	}
  #endif  
  
  #ifdef uart4_DMA 
  extern DMA_HandleTypeDef hdma_usart4_rx;
  if(__HAL_UART_GET_FLAG(&huart4,UART_FLAG_IDLE))	//如果置1了，代表已经接收完毕了
	{
		__HAL_UART_CLEAR_IDLEFLAG(&huart4);
		huart4.Instance->ISR;
		huart4.Instance->RDR;
		HAL_UART_DMAStop(&huart4);
		Uart4_Data.Uart_Receive_Cunt=Data_Len_Max-hdma_usart4_rx.Instance->CNDTR;
		DMA1_Channel1->CNDTR=Data_Len_Max;
		Uart4_Data.Uart_Receive_Complete = 1;		//完成了接收，在前台任务要将DMA再次打开
	}
  #endif  
  
  #ifdef Use_Shell
    Shell_Intercep();
  #endif
}
/**********************************************
函数名称：Uart_Call_Back()
函数作用：处理中断接收数据
使用		：此函数不需要外部调用，由系统自动回调
调用说明：
外部声明：             
**********************************************/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    /* 判断是哪个串口触发的中断 */
    #ifdef uart1_IT
    if(huart ->Instance == USART1)
    {
        //调用shell处理数据的接口
//			printf("uart1 IT,%d\n",recv_buf); 

        //使能串口中断接收
     HAL_UART_Receive_IT(&huart1, (uint8_t*)&recv_buf, 1);
    }
    #endif
		#ifdef uart2_IT
    if(huart ->Instance == USART2)
    {
        //调用shell处理数据的接口
     shellHandler(&shell, recv_buf);

        //使能串口中断接收
     HAL_UART_Receive_IT(&huart2, (uint8_t*)&recv_buf, 1);
    }
    #endif
}




